﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using BluewaterSoft.Notepad.Data;
using System.Threading.Tasks;
using Windows.Storage.Pickers;
using Windows.Storage;
using Windows.UI.Notifications;
using Windows.Data.Xml.Dom;
using System.Text;
using Windows.UI.Popups;
using Windows.ApplicationModel.Activation;

// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238

namespace BluewaterSoft.Notepad
{
  /// <summary>
  /// An empty page that can be used on its own or navigated to within a Frame.
  /// </summary>
  public sealed partial class MainPage : Page
  {
    public MainPage()
    {
      this.InitializeComponent();
    }

    /// <summary>
    /// Invoked when this page is about to be displayed in a Frame.
    /// </summary>
    /// <param name="e">Event data that describes how this page was reached.  The Parameter
    /// property is typically used to configure the page.</param>
    protected async override void OnNavigatedTo(NavigationEventArgs e)
    {
      IActivatedEventArgs args = e.Parameter as IActivatedEventArgs;
      switch (args.Kind) { 
        case ActivationKind.Launch:
        this.DataContainer.DataContext = new TextContentData();
          break;
        case ActivationKind.File:
          FileActivatedEventArgs fa = args as FileActivatedEventArgs;
          var sf = fa.Files[0] as StorageFile;
          await LoadTextAsync(sf);
          break;
        default:
          // (void)
          break;
      }
    }




    private async void AddButton_Click(object sender, RoutedEventArgs e)
    {
      using (ButtonDisabler.Start(sender as Button))
      {
        bool canDiscard = await CanDiscard("新しく書く", "破棄して新しく編集を始める");
        if (!canDiscard)
          return;

        var dataSource = new TextContentData();
        dataSource.TextContent = string.Empty;
        this.DataContainer.DataContext = dataSource;
      }
    }

    private async void OpenFileButton_Click(object sender, RoutedEventArgs e)
    {
      using (ButtonDisabler.Start(sender as Button))
      {
        bool canDiscard = await CanDiscard("別のファイルを開く", "破棄して新しいファイルを開く");
        if (!canDiscard)
          return;

        FileOpenPicker picker = new FileOpenPicker();
        picker.CommitButtonText = "テキストファイルを開く";
        picker.FileTypeFilter.Add(".txt");
        picker.FileTypeFilter.Add(".cs");
        picker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;
        picker.ViewMode = PickerViewMode.List;

        StorageFile file = await picker.PickSingleFileAsync();
        await this.LoadTextAsync(file);
      }
    }

    private async void SaveButton_Click(object sender, RoutedEventArgs e)
    {
      var dataSource = this.DataContainer.DataContext as TextContentData;
      if (!dataSource.IsChanged)
      {
        ShowToast("上書き保存はしません。", "テキストは編集されていません。保存する必要はありません。");

        return;
      }

      using (ButtonDisabler.Start(sender as Button))
      {
        if (dataSource.StorageFile == null)
          await SaveAsAsync();
        else
          await SaveAsync();
      }
    }

    private async void SaveAsButton_Click(object sender, RoutedEventArgs e)
    {
      using (ButtonDisabler.Start(sender as Button))
      {
        await SaveAsAsync();
      }
    }

    private async Task<bool> CanDiscard(string msgTitle, string okTitle)
    {
      var dataSource = this.DataContainer.DataContext as TextContentData;
      if (!dataSource.IsChanged)
        return true;

      var messageBox = new MessageDialog("編集中のテキストはまだ保存されていません。破棄してもよいですか?",
          msgTitle);
      messageBox.Commands.Add(new UICommand(okTitle));
      messageBox.Commands.Add(new UICommand("キャンセル"));
      messageBox.DefaultCommandIndex = 1;

      var cmd = await messageBox.ShowAsync();
      return (cmd.Label != "キャンセル");
    }







    private async Task LoadTextAsync(StorageFile file)
    {
      if (file == null)
        return;

      var dataSource = new TextContentData();

      dataSource.StorageFile = file;
      //this.FilePath = file.Path;
      //this.FileName = file.Name;

      using (Stream s = await file.OpenStreamForReadAsync())
      using (StreamReader r = new StreamReader(s))
        dataSource.TextContent = await r.ReadToEndAsync();

      this.DataContainer.DataContext = dataSource;
    }

    private async Task SaveAsAsync()
    {
      var dataSource = this.DataContainer.DataContext as TextContentData;

      FileSavePicker picker = new FileSavePicker();
      picker.CommitButtonText = "この名前でテキストファイルを保存する";
      picker.DefaultFileExtension = ".txt";
      picker.FileTypeChoices.Add("テキスト", new string[] { ".txt", });
      picker.SuggestedSaveFile = dataSource.StorageFile;

      StorageFile file = await picker.PickSaveFileAsync();
      if (file == null)
      {
        ShowToast("保存されていません。", "保存先のファイルが指定されなかったので、保存は実行されませんでした。");

        return;
      }

      dataSource.StorageFile = file;
      await SaveAsync();
    }

    private async Task SaveAsync()
    {
      var dataSource = this.DataContainer.DataContext as TextContentData;

      using (Stream s = await dataSource.StorageFile.OpenStreamForWriteAsync())
      using (StreamWriter w = new StreamWriter(s, Encoding.UTF8))
      {
        await w.WriteAsync(dataSource.TextContent);
      }

      //await this.LoadTextAsync(this._file); //TODO:再読み込みは必要か?

      ShowToast("保存しました。",
        string.Format("保存先: {0}", dataSource.StorageFile.Path));
    }




    internal static void ShowToast(string line1, string line2)
    {
      ToastTemplateType temp = ToastTemplateType.ToastText02;
      XmlDocument toastXml = ToastNotificationManager.GetTemplateContent(temp);
      XmlNodeList toastTextElements = toastXml.GetElementsByTagName("text");
      toastTextElements[0].AppendChild(toastXml.CreateTextNode(line1));
      toastTextElements[1].AppendChild(toastXml.CreateTextNode(line2));

      ToastNotification toast = new ToastNotification(toastXml);
      ToastNotificationManager.CreateToastNotifier().Show(toast);
    }

  }
}
